package mysql

import (
	"time"

	"mxshop_srvs/order_srv/model"
	proto "mxshop_srvs/order_srv/proto/gen/v1"
)

type CartItemRecord struct {
	ID      int32
	UserId  int32
	GoodsId int32
	Nums    int32
	Checked bool
}

// CartItemCount 获取用户购物车商品总数
func (g *Gorm) CartItemCount(userID int32) (count int64, err error) {
	result := g.db.Model(&model.ShoppingCart{}).Where(map[string]interface{}{
		"user_id": userID,
	}).Count(&count)
	if err := result.Error; err != nil {
		return count, err
	}
	return count, nil
}

type CartItem struct {
	ID     int32
	UserID int32
	GoodID int32
}

// GetCartItem 获取用户购物车商品
func (g *Gorm) GetCartItem(item CartItem) (CartItemRecord, error) {
	var cartItem CartItemRecord
	err := g.db.Model(&model.ShoppingCart{}).Where(&model.ShoppingCart{
		BaseModel: model.BaseModel{ID: item.ID},
		UserID:    item.UserID,
		GoodsID:   item.GoodID,
	}).First(&cartItem).Error
	if err != nil {
		return cartItem, err
	}
	return cartItem, nil
}

// GetCartItems 获取用户购物车商品列表
func (g *Gorm) GetCartItems(userID int32, checked bool) ([]*CartItemRecord, error) {
	cartItems := make([]*CartItemRecord, 0, 8)
	err := g.db.Model(&model.ShoppingCart{}).Where(map[string]interface{}{
		"user_id": userID,
	}).Where(&model.ShoppingCart{
		Checked: checked,
	}).Find(&cartItems).Error
	if err != nil {
		return cartItems, err
	}
	return cartItems, nil
}

// CreateCartItem 将商品添加到购物车
func (g *Gorm) CreateCartItem(i CartItemRecord) (*CartItemRecord, error) {
	var cartItem = &model.ShoppingCart{
		UserID:  i.UserId,
		GoodsID: i.GoodsId,
		Nums:    i.Nums,
		Checked: i.Checked,
	}
	result := g.db.Create(cartItem)
	if err := result.Error; err != nil {
		return &i, err
	}
	i.ID = cartItem.ID
	return &i, nil
}

// UpdateCartItem 更新购物车商品
func (g *Gorm) UpdateCartItem(i CartItemRecord) error {
	db := g.db.Model(&model.ShoppingCart{
		BaseModel: model.BaseModel{ID: i.ID},
	}).Select("checked")

	if i.Nums > 0 {
		db = db.Select("nums", "checked")
	}

	return db.Updates(model.ShoppingCart{
		Nums:    i.Nums,
		Checked: i.Checked,
	}).Error
}

// DeleteCartItem 删除购物车商品
func (g *Gorm) DeleteCartItem(req *proto.DeleteCartItemRequest) (int64, error) {
	if req.Id != 0 {
		result := g.db.Where(&model.ShoppingCart{
			UserID: req.UserId,
		}).Delete(&model.ShoppingCart{}, req.Id)
		return result.RowsAffected, result.Error
	}
	result := g.db.Where(&model.ShoppingCart{
		UserID:  req.UserId,
		GoodsID: req.GoodsId,
	}).Delete(&model.ShoppingCart{})
	return result.RowsAffected, result.Error
}

// DeleteCheckedCartItem 删除购物车选中的商品
func (g *Gorm) DeleteCheckedCartItem(userID int32) error {
	return g.db.Where(&model.ShoppingCart{UserID: userID, Checked: true}).Delete(&model.ShoppingCart{}).Error
}

// UserOrderCount 获取用户订单总数
func (g *Gorm) UserOrderCount(userID int32) (count int64, err error) {
	err = g.db.Model(&model.Order{}).Where(&model.Order{UserID: userID}).Count(&count).Error
	return
}

// GetUserOrderList 获取用户订单列表
func (g *Gorm) GetUserOrderList(req *proto.OrderFilterRequest) ([]*model.Order, error) {
	orders := make([]*model.Order, 0, 8)
	err := g.db.Scopes(Paginate(int(req.Pages), int(req.PagePerNums))).Where(&model.Order{
		UserID: req.UserId}).Find(&orders).Error
	return orders, err
}

// GetOrderDetail 获取订单详情
func (g *Gorm) GetOrderDetail(req *proto.OrderDetailRequest) (model.Order, error) {
	var order model.Order
	err := g.db.Where(&model.Order{
		UserID: req.UserId,
	}).Take(&order, req.OrderId).Error
	return order, err
}

// GetOrderGoods 获取订单商品信息
func (g *Gorm) GetOrderGoods(orderID int32) ([]*model.OrderGoods, error) {
	orderGoods := make([]*model.OrderGoods, 0, 8)
	err := g.db.Where(&model.OrderGoods{OrderID: orderID}).Find(&orderGoods).Error
	return orderGoods, err
}

type OrderInfo struct {
	UserID          int32
	OrderSn         int64
	AmountCents     int32
	Address         string
	ConsigneeName   string
	ConsigneeMobile string
	Post            string
}

func OrderInfoToModel(orderInfo OrderInfo) model.Order {
	return model.Order{
		UserID:          orderInfo.UserID,
		OrderSn:         orderInfo.OrderSn,
		AmountCents:     orderInfo.AmountCents,
		Address:         orderInfo.Address,
		ConsigneeName:   orderInfo.ConsigneeName,
		ConsigneeMobile: orderInfo.ConsigneeMobile,
		Post:            orderInfo.Post,
	}
}

// CreateOrder 创建订单
func (g *Gorm) CreateOrder(orderInfo OrderInfo) (int32, error) {
	var order = OrderInfoToModel(orderInfo)
	order.Status = model.OSTradeCreation // 初始化订单状态
	err := g.db.Create(&order).Error
	return order.ID, err
}

func (g *Gorm) CreateOrderByTrans(orderInfo OrderInfo, orderGoods []*model.OrderGoods, batchSize int) (int32, error) {
	tx := g.db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	if err := tx.Error; err != nil {
		return 0, err
	}

	// 1. 创建订单
	var order = OrderInfoToModel(orderInfo)
	order.Status = model.OSTradeCreation // 初始化订单状态
	err := tx.Create(&order).Error
	if err != nil {
		tx.Rollback()
		return 0, err
	}

	// 把orderID插入到orderGoods中
	for _, goods := range orderGoods {
		goods.OrderID = order.ID
	}

	// 2. 批量插入orderGoods
	err = tx.CreateInBatches(orderGoods, batchSize).Error
	if err != nil {
		tx.Rollback()
		return 0, err
	}

	// 3. 从购物车中删除已购买记录
	err = tx.Where(&model.ShoppingCart{UserID: orderInfo.UserID, Checked: true}).Delete(&model.ShoppingCart{}).Error
	if err != nil {
		tx.Rollback()
		return 0, err
	}

	return order.ID, tx.Commit().Error
}

// GetOrder 获取订单
func (g *Gorm) GetOrder(orderID int32, orderSn int64) (model.Order, error) {
	var order model.Order
	err := g.db.Model(&model.Order{}).Where(&model.Order{
		BaseModel: model.BaseModel{ID: orderID},
		OrderSn:   orderSn,
	}).First(&order).Error
	if err != nil {
		return order, err
	}
	return order, nil
}

// BatchInsertOrderGoods 批量插入订单商品
func (g *Gorm) BatchInsertOrderGoods(orderGoods []*model.OrderGoods, batchSize int) error {
	return g.db.CreateInBatches(orderGoods, batchSize).Error
}

// UpdateOrderStatus 更新订单状态
func (g *Gorm) UpdateOrderStatus(req *proto.UpdateOrderStatusRequest) (int64, error) {
	result := g.db.Model(&model.Order{}).Where(&model.Order{
		BaseModel: model.BaseModel{ID: req.OrderId},
		OrderSn:   req.OrderSn,
	}).Updates(model.Order{
		Status:  model.OrderStatus(req.Status),
		PayType: model.PayType(req.PaymentType),
	})
	return result.RowsAffected, result.Error
}

// UpdateOrder 更新订单
func (g *Gorm) UpdateOrder(req *proto.UpdateOrderRequest) (int64, error) {
	nowTime := time.Now()
	result := g.db.Model(&model.Order{}).Where(&model.Order{
		BaseModel: model.BaseModel{ID: req.OrderId},
		OrderSn:   req.OrderSn,
	}).Updates(model.Order{
		Status:  model.OrderStatus(req.Status),
		PayType: model.PayType(req.PaymentType),
		TradeNo: req.TradeNo,
		PayTime: &nowTime,
	})
	return result.RowsAffected, result.Error
}
